#include <stdio.h>

#define ROWS 3
#define COLS 4

void local_check(void);

void swap();

void swap_1(int a, int b);

void swap_2(int *a, int *b);

void multi_arr();

void fun_arr();

void sum_rows(int array[][4], int rows);

void sum_cols(int array[][4], int cols);

// 等价于sum_cols
void sum_cols_1(int (*array)[4], int cols);

void variable_length_array(int rows, int cols, int arr[ *][ *]);

int main(void)
{
    int array[4][2] = {
        {2, 4},
        {6, 8},
        {1, 3},
        {5, 7}
    };
    variable_length_array(4, 2, array);
    return 0;
}

void local_check(void)
{
    int i = 2, j = 3;
    printf("i = %d, &i = %p\n", i, &i);
    printf("j = %d, &j = %p\n", j, &j);
}

void swap()
{
    int a = 2;
    int b = 3;

    printf("a = %d, &a = %p; b = %d, &b = %p\n", a, &a, b, &b);
    swap_2(&a, &b);
    printf("a = %d, &a = %p; b = %d, &b = %p\n", a, &a, b, &b);

}

void swap_1(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
    // 变量a, b的值是 swap()值的复制, 并非 swap()中的a, b
    printf("swap_1 --- a = %d, &a = %p; b = %d, &b = %p\n", a, &a, b, &b);
}

void swap_2(int *a, int *b)
{
    int temp;

    temp = *a;
    *a = *b;
    *b = temp;
    // 此处&a,&b存放的是*a, *b的地址而非a, b的内存地址
    // *&a, *&b才是*a, *b存放的真实值
    printf("swap_2 --- a = %d, &a = %p, *&a = %p; b = %d, &b = %p, *&b = %p\n", *a, &a, *&a, *b, &b, *&b);
}

void multi_arr()
{
    int array[4][2] = {
        {2, 4},
        {6, 8},
        {1, 3},
        {5, 7}
    };

    // int类型占4位
    // 地址相差8, 加一单位的二维数组(2单位的int)
    printf("array = [%p], array + 1 = [%p]\n", array, array + 1);
    // 地址相差4, array[0]访问的二维数组, 二维数组加一单位的int
    // array[0] = array, 原因是array[0]的地址与array[0][0]的地址相同, 数组的首地址即第一个数据的地址.
    printf("array[0] = [%p], array[0] + 1 = [%p]\n", array[0], array[0] + 1);
    // 地址相差4, *array解引用后是二维数组, 二维数组加一单位的int
    printf("*array = [%p], *array + 1 = [%p]\n", *array, *array + 1);
    // 直接访问数组值
    printf("array[0][0] = [%d]\n", array[0][0]);
    // 解绑一维数组, 访问二维数组的第一个值
    printf("*array[0] = [%d]\n", *array[0]);
    printf("**array = [%d]\n", **array);
    // 数组的直接访问
    printf("array[2][1] = [%d]\n", array[2][1]);
    // *(array + 2)解绑到二维数组的[2]位置, *([2] + 1)解绑到二维数组的[2][1]处
    printf("*(*(array + 2) + 1) = [%d]\n", *(*(array + 2) + 1));

    printf("-----------------------------\n");

    /*
     * 指向二维数组的指针
     * int *pz[2]; 因为'[]'优先级 > '*', 所以声明的一个长度为2的数组, 数组内容是指向int类型的指针
     * int (*pz)[2]; '()'提高了优先级, 所以声明的是一个指针, 指向的一个长度为2的int类型的数组
     */
    int (*pz)[2];
    pz = array;

    // 以下结果与上方结果相同
    printf("pz = [%p], pz + 1 = [%p]\n", pz, pz + 1);
    printf("pz[0] = [%p], pz[0] + 1 = [%p]\n", pz[0], pz[0] + 1);
    printf("*pz = [%p], *pz + 1 = [%p]\n", *pz, *pz + 1);
    printf("pz[0][0] = [%d]\n", pz[0][0]);
    printf("*pz[0] = [%d]\n", *pz[0]);
    printf("**pz = [%d]\n", **pz);
    printf("pz[2][1] = [%d]\n", pz[2][1]);
    printf("*(*(pz + 2) + 1) = [%d]\n", *(*(pz + 2) + 1));
}

void fun_arr()
{
    int array[ROWS][COLS] = {
        {1, 2,  3,  4},
        {5, 6,  7,  8},
        {9, 10, 11, 12}
    };

    printf("rows sum\n");
    sum_rows(array, ROWS);
    printf("cols sum\n");
    sum_cols(array, COLS);
}

void sum_rows(int array[][4], int rows)
{
    for (int i = 0; i < rows; ++i)
    {
        int sum = 0;
        for (int j = 0; j < COLS; j++)
        {
            sum += array[i][j];
        }
        printf("row: [%d], sum: [%d]\n", i, sum);
    }
}

void sum_cols(int array[][4], int cols)
{
    sum_cols_1(array, cols);
}

// 等价于sum_cols
void sum_cols_1(int (*array)[4], int cols)
{
    for (int i = 0; i < cols; ++i)
    {
        int sum = 0;
        for (int j = 0; j < ROWS; j++)
        {
            sum += array[j][i];
        }
        printf("col: [%d], sum: [%d]\n", i, sum);
    }
}

void variable_length_array(int rows, int cols, int arr[rows][cols])
{
    for (int i = 0; i < rows; i++)
    {
        printf("[");
        for (int j = 0; j < cols; ++j)
        {
            if (j == cols - 1)
            {
                printf("%d", arr[i][j]);
            } else{
                printf("%d, ", arr[i][j]);
            }
        }
        printf("]\n");
    }
}
